<!DOCTYPE html>
<html>
<head>
    <title>Physics Diagram of a Wave on a String</title>
</head>
<body>

<canvas id="physicsCanvas" width="500" height="400" style="border:1px solid #d3d3d3;"></canvas>

<script>
    const canvas = document.getElementById('physicsCanvas');
    const ctx = canvas.getContext('2d');

    // Clear canvas
    ctx.fillStyle = 'white';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // Style settings
    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'black';
    ctx.lineWidth = 2;

    // Define coordinate system origin on canvas
    const cx = 300;
    const cy = 200;

    // --- Draw Axes and String ---
    
    // Draw Y-axis first
    const yAxisStartY = 300;
    const yAxisEndY = 100;
    ctx.beginPath();
    ctx.moveTo(cx, yAxisStartY);
    ctx.lineTo(cx, yAxisEndY);
    ctx.stroke();
    // Y-axis arrowhead
    let headlen = 10;
    let angleY = Math.atan2(yAxisEndY - yAxisStartY, 0);
    ctx.beginPath();
    ctx.moveTo(cx, yAxisEndY);
    ctx.lineTo(cx - headlen * Math.cos(angleY - Math.PI / 6), yAxisEndY - headlen * Math.sin(angleY - Math.PI / 6));
    ctx.lineTo(cx - headlen * Math.cos(angleY + Math.PI / 6), yAxisEndY - headlen * Math.sin(angleY + Math.PI / 6));
    ctx.closePath();
    ctx.fill();

    // Draw the String/Wave Packet/X-axis as one continuous path
    ctx.beginPath();
    // Part of the string to the left of the wave packet
    ctx.moveTo(20, cy);
    const waveStartX = 140;
    ctx.lineTo(waveStartX, cy);

    // The wave packet itself (resistor-like shape)
    const waveHeight = 10;
    const zigWidth = 20;
    let currentX = waveStartX;
    ctx.lineTo(currentX + zigWidth / 2, cy - waveHeight); 
    currentX += zigWidth / 2;
    ctx.lineTo(currentX + zigWidth, cy + waveHeight); 
    currentX += zigWidth;
    ctx.lineTo(currentX + zigWidth, cy - waveHeight); 
    currentX += zigWidth;
    ctx.lineTo(currentX + zigWidth, cy + waveHeight); 
    currentX += zigWidth;
    ctx.lineTo(currentX + zigWidth, cy - waveHeight); 
    currentX += zigWidth;
    ctx.lineTo(currentX + zigWidth / 2, cy); 
    currentX += zigWidth / 2;
    
    // Part of the string to the right of the wave packet, up to the end of the axis
    const axisEndX = 480;
    ctx.lineTo(axisEndX, cy);
    ctx.stroke();

    // X-axis arrowhead
    const angleX = 0;
    ctx.beginPath();
    ctx.moveTo(axisEndX, cy);
    ctx.lineTo(axisEndX - headlen * Math.cos(angleX - Math.PI / 6), cy - headlen * Math.sin(angleX - Math.PI / 6));
    ctx.lineTo(axisEndX - headlen * Math.cos(angleX + Math.PI / 6), cy - headlen * Math.sin(angleX + Math.PI / 6));
    ctx.closePath();
    ctx.fill();

    // --- Draw Labels ---
    ctx.font = 'italic 18px serif';
    ctx.textAlign = 'left';
    ctx.textBaseline = 'middle';
    ctx.fillText('x', axisEndX + 5, cy);
    ctx.textAlign = 'center';
    ctx.fillText('y', cx, yAxisEndY - 12);
    ctx.fillText('m', cx, cy + 22);

    // --- Draw the Mass (bead) ---
    ctx.beginPath();
    ctx.arc(cx, cy, 5, 0, 2 * Math.PI, false);
    ctx.fill();

    // --- Draw the Propagation Arrow ---
    const arrowY = cy - 40;
    const arrowStartX = 160;
    const arrowEndX = 240;
    ctx.beginPath();
    ctx.moveTo(arrowStartX, arrowY);
    ctx.lineTo(arrowEndX, arrowY);
    ctx.stroke();
    // Arrowhead for propagation arrow
    const angleProp = 0;
    ctx.beginPath();
    ctx.moveTo(arrowEndX, arrowY);
    ctx.lineTo(arrowEndX - headlen * Math.cos(angleProp - Math.PI / 6), arrowY - headlen * Math.sin(angleProp - Math.PI / 6));
    ctx.lineTo(arrowEndX - headlen * Math.cos(angleProp + Math.PI / 6), arrowY - headlen * Math.sin(angleProp + Math.PI / 6));
    ctx.closePath();
    ctx.fill();
    
    // --- Draw the Figure Caption ---
    ctx.font = 'bold 16px serif';
    ctx.textAlign = 'center';
    ctx.fillText('Fig. 1.218.', canvas.width / 2, 360);

</script>

</body>
</html>